package com.arong.list.arrayList;

import java.util.ArrayList;
import java.util.ConcurrentModificationException;
import java.util.Iterator;
import java.util.NoSuchElementException;

import com.arong.list.arrayList.ArongArrayList;

import static com.arong.list.arrayList.ArongArrayList.modCount;

public class ArongItr<E>
        extends ArongArrayList
        implements Iterator<E> {

    /**
     * 下一个访问元素的位置
     */
    int cursor;

    /**
     * 上一次访问元素的位置
     * 初始化为-1，移除时为-1
     */
    int lastRet = -1;

    /**
     * 校验 fast-fail 异常
     * 修改过程中数组发生变化会抛出 ConcurrentModificationException 异常
     */
    int expectedModCount = modCount;

    ArongItr() {}

    @Override
    public boolean hasNext() {
        return cursor != size;
    }

    @Override
    public E next() {
        // 校验是否数组发生了变化
        checkForComodification();
        int i = cursor;
        // 判断如果超过 size 范围，抛出 NoSuchElementException 异常
        if(i >= size) {
            throw new NoSuchElementException();
        }
        ArongArrayList<E> eArongArrayList = new ArongArrayList<>();
        Object[] elementData = eArongArrayList.elementData;
        // 超出大小说明可能被修改了
        if (i >= elementData.length)
            throw new ConcurrentModificationException();
        // cursor 指向下一个位置
        cursor = i + 1;
        // 返回当前位置的元素
        return (E) elementData[lastRet = i];
    }

    public void remove() {
        // 如果 lastRet 小于 0 ，说明没有指向任何元素，抛出 IllegalStateException 异常
        if (lastRet < 0)
            throw new IllegalStateException();
        // 校验是否数组发生了变化
        checkForComodification();

        try {
            // 移除 lastRet 位置的元素
            ArongArrayList<E> eArongArrayList = new ArongArrayList<>();
            eArongArrayList.remove(lastRet);
            // cursor 指向 lastRet 位置，因为被移了，所以需要后退下
            cursor = lastRet;
            // lastRet 标记为 -1 ，因为当前元素被移除了
            lastRet = -1;
            // 记录新的数组的修改次数
            expectedModCount = modCount;
        } catch (IndexOutOfBoundsException ex) {
            throw new ConcurrentModificationException();
        }
    }

    final void checkForComodification() {
        if (modCount != expectedModCount)
            throw new ConcurrentModificationException();
    }
}
